---
layout: docs
page_title: SSH ProxyCommand Workflow
description: How to manage SSH proxy configuration with Boundary
---

# SSH ProxyCommand Workflow

The most common pattern for using Boundary to SSH is with the built-in `boundary connect ssh` command. However,
there are more idiomatic approaches that can be employed to make Boundary transparent to users, and at the same
time simplify common developer and operator workflows. Using `ProxyCommand` to execute a proxy when invoking the
SSH client is a common practice. In this workflow, we'll cover configuring your SSH client to execute the
`boundary` command, enabling a simplified SSH workflow that leverages Boundary's authenticated proxy for accessing
targets.

## SSH Configuration

Start by configuring a `Host` entry in `.ssh/ssh_config` for `localhost`:

```bash
Host ttcp_*
  ProxyCommand sh -c "boundary connect -target-id %n -exec nc -- {{boundary.ip}} {{boundary.port}}"
```

The `ProxyCommand` tells the SSH client to invoke `boundary connect`. We are passing the `-exec nc` flag to
`boundary connect` to wrap [netcat](http://netcat.sourceforge.net/), and then pass the `boundary.ip` and `boundary.port`
variables as arguments to `nc`. This allows us to proxy our SSH connection through a local netcat tunnel that's
managed as a Boundary session.

When you run `ssh ttcp_1234567890` (example target ID), SSH will invoke `boundary connect`, and will tunnel the traffic through
the local Boundary proxy in a wrapped netcat session, passing in the target ID as the hostname to the `boundary` command.

## Authenticate to Boundary

Before `ssh` can invoke `boundary connect` you need to authenticate. In this example, we're using `boundary dev` with the
default username (admin) and password (password), and because this auth method is the primary that resides in the global 
scope, we can use the short form of the authenticate command with no extra flags:

```bash
$ boundary authenticate
```

## SSH to Target

Running Boundary in [dev mode](/boundary/docs/oss/installing/dev-mode) creates other
default resources such as a target and auth method. The default target (ttcp_1234567890) is already setup with a host
at `localhost` and a default port of `22`.

You can simply run `ssh` as you normally would and all the traffic will be proxied over the Boundary proxy to your target machine:

```bash
$ ssh ttcp_1234567890
Password:
Last login: Thu Nov 19 10:32:09 2020
➜  ~
```

On the controller, you should see the session being invoked in the logs:

```bash
controller.worker-handler: connection established: session_id=s_WkaQbqmrJx connection_id=sc_RDYNFFI2M4 client_tcp_address=127.0.0.1 client_tcp_port=57421 endpoint_tcp_address=::1 endpoint_tcp_port=22
```

You can inspect the session on the CLI as well:

```bash
$  boundary sessions read -id $(boundary sessions list -scope-id p_1234567890 -format json | jq '.[0]["id"]' | tr -d '"')

Session information:
  Auth Token ID:       at_a8itRfDSyV
  Created Time:        Thu, 19 Nov 2020 10:52:44 PST
  Endpoint:            tcp://localhost:22
  Expiration Time:     Thu, 19 Nov 2020 18:52:44 PST
  Host ID:             hst_1234567890
  Host Set ID:         hsst_1234567890
  ID:                  s_WkaQbqmrJx
  Status:              active
  Target ID:           ttcp_1234567890
  Type:                tcp
  Updated Time:        Thu, 19 Nov 2020 10:52:47 PST
  User ID:             u_1234567890
  Version:             2

  Scope:
    ID:                p_1234567890
    Name:              Generated project scope
    Parent Scope ID:   o_1234567890
    Type:              project

  States:
    Start Time:        Thu, 19 Nov 2020 10:52:47 PST
    Status:            active

    End Time:          Thu, 19 Nov 2020 10:52:47 PST
    Start Time:        Thu, 19 Nov 2020 10:52:44 PST
    Status:            pending
```

# Advanced Usage

Another way to access targets using ProxyCommand is by setting the `Host` value to the target domain instead of the target ID.
This is useful if you want to use the domain name instead of the target ID when forking SSH. An extra step is required to make this
work where you must authorize the session to the target and store it in your environment since we're no longer passing the target
ID to the SSH command. This will allow Boundary to pull the target information from the token you created in the `authorize session`
command.

## Configure SSH

```bash
Host localhost
    # requires BOUNDARY_CONNECT_AUTHZ_TOKEN to be set from authorize-session command
    ProxyCommand sh -c "boundary connect -exec nc -- {{boundary.ip}} {{boundary.port}}"
```

## Authenticate to Boundary

Before `ssh` can invoke `boundary connect` you need to authenticate. In this example, we're using `boundary dev` with the
default username (admin) and password (password):

```bash
$ boundary authenticate
```

## Authorize the Session

Running Boundary in [dev mode](/boundary/docs/oss/installing/dev-mode) creates other
default resources such as a target and auth method. The default target (ttcp_1234567890) is already setup with a host
at `localhost` and a default port of `22`.

Authorize a session to the default target and store the token in the `BOUNDARY_CONNECT_AUTHZ_TOKEN` environment variable.
This will be used by Boundary when it's invoked by SSH:

```bash
$ export BOUNDARY_CONNECT_AUTHZ_TOKEN=$(boundary targets authorize-session -id ttcp_1234567890 -format json | jq '.authorization_token' | tr -d '"')
```

## SSH to Target

```bash
$ ssh user@localhost
Password:
Last login: Thu Nov 19 10:32:09 2020
➜  ~
```
